home *** CD-ROM | disk | FTP | other *** search
/ Suzy B Software 2 / Suzy B Software CD-ROM 2 (1994).iso / new_file / mintprgs / mint112s / mint112s.lzh / signal.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-14  |  18.1 KB  |  682 lines

  1. /*
  2. Copyright 1990,1991,1992 Eric R. Smith.
  3. Copyright 1992,1993,1994 Atari Corporation.
  4. All rights reserved.
  5. */
  6.  
  7. /* signal.c:: signal handling routines */
  8.  
  9. #include "mint.h"
  10.  
  11. void (*sig_routine)();    /* used in intr.s */
  12. short sig_exc;        /* used in intr.s */
  13.  
  14. /*
  15.  * killgroup(pgrp, sig, priv): send a signal to all members of a process group
  16.  * returns 0 on success, or an error code on failure
  17.  * priv is non-zero if the signal is generated by the kernel, otherwise
  18.  * access privileges are checked
  19.  */
  20.  
  21. long
  22. killgroup(pgrp, sig, priv)
  23.     int pgrp, sig, priv;
  24. {
  25.     PROC *p;
  26.     int found = 0;
  27.     long retval = EFILNF;
  28.  
  29.     if (pgrp < 0)
  30.         return EINTRN;
  31.  
  32.     for (p = proclist; p; p = p->gl_next) {
  33.         if (p->pgrp == pgrp) {
  34.           if (!priv && sig != SIGCONT && curproc->euid
  35.               && curproc->euid != p->euid && curproc->ruid != p->ruid)
  36.             retval = EACCDN;
  37.           else
  38.             {
  39.             post_sig(p, sig);
  40.             found++;
  41.             }
  42.         }
  43.     }
  44.     if (found) {
  45.         return 0;
  46.     } else {
  47.         return retval;
  48.     }
  49. }
  50.  
  51. /* post_sig: post a signal as being pending. It is assumed that the
  52.    caller has already verified that "sig" is a valid signal, and
  53.    moreover it is the caller's responsibility to call check_sigs()
  54.    if it's possible that p == curproc
  55.  */
  56.  
  57. void
  58. post_sig(p, sig)
  59.     PROC *p;
  60.     int sig;
  61. {
  62.     ulong sigm;
  63.     short sr;
  64.  
  65. /* if process is ignoring this signal, do nothing
  66.  * also: signal 0 is SIGNULL, and should never be delivered through
  67.  * the normal channels (indeed, it's filtered out in dossig.c,
  68.  * but the extra sanity check here is harmless). The kernel uses
  69.  * signal 0 internally for some purposes, but it is handled
  70.  * specially (see supexec() in xbios.c, for example).
  71.  */
  72. /* If the process is traced, the tracer should always be notified. */
  73.     if (sig == 0 || (p->sighandle[sig] == SIG_IGN && !p->ptracer))
  74.         return;
  75.  
  76. /* if the process is already dead, do nothing */
  77.     if (p->wait_q == ZOMBIE_Q || p->wait_q == TSR_Q)
  78.         return;
  79.  
  80. /* mark the signal as pending */
  81.     sigm = (1L << (unsigned long)sig);
  82.     p->sigpending |= sigm;
  83.  
  84. /* if the signal is masked, do nothing further */
  85. /* note: some signals can't be masked, and we handle those elsewhere so
  86.  * that p->sigmask is always valid. SIGCONT is among the unmaskable
  87.  * signals
  88.  */
  89.     if ( (p->sigmask & sigm) != 0 )
  90.         return;
  91.  
  92. /* otherwise, make sure the process is awake */
  93.     sr = spl7();
  94.     if (p->wait_q && p->wait_q != READY_Q) {
  95.         rm_q(p->wait_q, p);
  96.         add_q(READY_Q, p);
  97.     }
  98.     spl(sr);
  99. }
  100.  
  101. /*
  102.  * special version of kill that can be called from an interrupt
  103.  * handler or device driver
  104.  * it also accepts negative numbers to send signals to groups
  105.  */
  106. long ARGS_ON_STACK
  107. ikill(pid,sig)
  108.     int pid;
  109.     int sig;
  110. {
  111.     PROC *p;
  112.     long r;
  113.  
  114.     if (sig < 0 || sig >= NSIG)
  115.         return ERANGE;
  116.  
  117.     if (pid < 0)
  118.         r = killgroup(-pid, sig, 1);
  119.     else if (pid == 0)
  120.         r = killgroup(curproc->pgrp, sig, 1);
  121.     else {
  122.         p = pid2proc(pid);
  123.         if (p == 0 || p->wait_q == ZOMBIE_Q || p->wait_q == TSR_Q) {
  124.             return EFILNF;
  125.         }
  126.  
  127. /* if the user sends signal 0, don't deliver it -- for users, signal
  128.  * 0 is a null signal used to test the existence of a process
  129.  */
  130.         if (sig != 0)
  131.             post_sig(p, sig);
  132.         r = 0;
  133.     }
  134.     return r;
  135. }
  136.  
  137. /*
  138.  * check_sigs: see if we have any signals pending. if so,
  139.  * handle them.
  140.  */
  141.  
  142. void
  143. check_sigs()
  144. {
  145.     ulong sigs, sigm;
  146.     int i;
  147.     short deliversig;
  148.  
  149.     if (curproc->pid == 0) return;
  150. top:
  151.     sigs = curproc->sigpending;
  152.     /* Always notify the tracer about signals sent. */
  153.     if (!curproc->ptracer || curproc->sigpending & 1L)
  154.       sigs &= ~(curproc->sigmask);
  155.  
  156.     if (sigs) {
  157.         sigm = 2;
  158. /* with tracing we need a mechanism to allow a signal to be delivered
  159.  * to the child (curproc); Fcntl(...TRACEGO...) passes a SIGNULL to indicate that we
  160.  * should really deliver the signal, hence its always safe to remove it
  161.  * from pending.
  162.  */
  163.         deliversig = (curproc->sigpending & 1L);
  164.         curproc->sigpending &= ~1L;
  165.  
  166.         for (i = 1; i < NSIG; i++) {
  167.             if (sigs & sigm) {
  168.                 curproc->sigpending &= ~sigm;
  169.                 if (curproc->ptracer && !deliversig &&
  170.                     i != SIGCONT && i != SIGKILL) {
  171.                     TRACE(("tracer being notified of signal %d", i));
  172.                     stop(i);
  173.         /* the parent may reset our pending signals, so check again */
  174.                     goto top;
  175.                 } else {
  176.                     ulong omask;
  177.  
  178.                     omask = curproc->sigmask;
  179.  
  180.         /* sigextra gives which extra signals should also be masked */
  181.                     curproc->sigmask |= curproc->sigextra[i] | sigm;
  182.                     handle_sig(i);
  183.  
  184.  
  185. /*
  186.  * POSIX.1-3.3.4.2(723) "If and when the user's signal handler returns
  187.  * normally, the original signal mask is restored."
  188.  *
  189.  * BUG?: This unmasking could unmask a pending signal which we will not
  190.  * see this time around (if the signal number is less than i) and which
  191.  * was not pending when we started; should we detect this condition and
  192.  * loop around for a second try? POSIX only guarantees delivery of
  193.  * one signal per kernel entry, so this shouldn't really be a problem.
  194.  */
  195.                     curproc->sigmask = omask;    /* unmask signals */
  196.                 }
  197.             }
  198.             sigm = sigm << 1;
  199.         }
  200.     }
  201. }
  202.  
  203. /*
  204.  * raise: cause a signal to be raised in the current process
  205.  */
  206.  
  207. void
  208. raise(sig)
  209.     int sig;
  210. {
  211.     post_sig(curproc, sig);
  212.     check_sigs();
  213. }
  214.  
  215. #ifdef EXCEPTION_SIGS
  216. /* exception numbers corresponding to signals */
  217. char excep_num[NSIG] =
  218. { 0, 0, 0, 0,
  219.   4,            /* SIGILL == illegal instruction */
  220.   9,            /* SIGTRAP == trace trap    */
  221.   4,            /* pretend SIGABRT is also illegal instruction */
  222.   8,            /* SIGPRIV == privileged instruction exception */
  223.   5,            /* SIGFPE == divide by zero */
  224.   0, 2,            /* SIGBUS == bus error */
  225.   3            /* SIGSEGV == address error */
  226. /* everything else gets zeros */
  227. };
  228.  
  229. /* a "0" means we don't print a message when it happens -- typically the
  230.    user is expecting a synchronous signal, so we don't need to report it
  231. */
  232.  
  233. const char *signames[NSIG] = { 0,
  234. 0, 0, 0, "ILLEGAL INSTRUCTION", "TRACE TRAP",
  235. 0, "PRIVILEGE VIOLATION", "DIVISION BY ZERO", 0, "BUS ERROR",
  236. "ADDRESS ERROR", "BAD SYSTEM CALL", 0, 0, 0,
  237. 0, 0, 0, 0, 0,
  238. 0, 0, 0, "CPU TIME EXHAUSTED", "FILE TOO BIG",
  239. 0, 0, 0, 0, 0
  240. };
  241.  
  242. /*
  243.  * replaces the TOS "show bombs" routine: for now, print the name of the
  244.  * interrupt on the console, and save info on the crash in the appropriate
  245.  * system area
  246.  */
  247.  
  248. void
  249. bombs(sig)
  250.     int sig;
  251. {
  252.     long *procinfo = (long *)0x380L;
  253.     int i;
  254.     CONTEXT *crash;
  255.     extern int no_mem_prot;
  256.  
  257.     if (sig < 0 || sig > 31) {
  258.         ALERT("bombs(%d): sig out of range", sig);
  259.     }
  260.     else if (signames[sig]) {
  261.         if (!no_mem_prot && sig == SIGBUS) {
  262.             /* already reported by report_buserr */
  263.         } else {
  264.             /* uk: give some more information in case of a crash, so that a
  265.              *     progam which shared text can be debugged better.
  266.              */
  267.             BASEPAGE *base;
  268.             long ptext = 0, pdata = 0, pbss = 0;
  269.  
  270.             base = curproc->base;
  271.             if (base)   /* can it happen, that base == NULL???? */
  272.             {
  273.                 ptext = base->p_tbase;
  274.                 pdata = base->p_dbase;
  275.                 pbss = base->p_bbase;
  276.             }
  277.             ALERT("%s: User PC=%lx (basepage=%lx, text=%lx, data=%lx, bss=%lx)",
  278.                 signames[sig],
  279.                 curproc->exception_pc, curproc->base, ptext, pdata, pbss);
  280.         }
  281. /* save the processor state at crash time */
  282. /* assumes that "crash time" is the context curproc->ctxt[SYSCALL] */
  283. /* BUG: this is not true if the crash happened in the kernel; in the
  284.  * latter case, the crash context wasn't saved anywhere.
  285.  */
  286.         crash = &curproc->ctxt[SYSCALL];
  287.         *procinfo++ = 0x12345678L;    /* magic flag for valid info */
  288.         for (i = 0; i < 15; i++)
  289.             *procinfo++ = crash->regs[i];
  290.         *procinfo++ = curproc->exception_ssp;
  291.         *procinfo++ = ((long)excep_num[sig]) << 24L;
  292.         *procinfo = crash->usp;
  293.  
  294. /* we're also supposed to save some info from the supervisor stack. it's not
  295.  * clear what we should do for MiNT, since most of the stuff that used to be
  296.  * on the stack has been put in the CONTXT struct. Moreover, we don't want
  297.  * to crash because of an attempt to access illegal memory. Hence, we do
  298.  * nothing here...
  299.  */
  300.     } else {
  301.         TRACE(("bombs(%d)", sig));
  302.     }
  303. }
  304. #endif
  305.  
  306. /*
  307.  * handle_sig: do whatever is appropriate to handle a signal
  308.  */
  309.  
  310. long unwound_stack = 0;
  311.  
  312. void
  313. handle_sig(sig)
  314.     int sig;
  315. {
  316.     long oldstack, newstack;
  317.     long *stack;
  318.     CONTEXT *call, contexts[2];
  319. #define oldsysctxt (contexts[0])
  320. #define newcurrent (contexts[1])
  321.  
  322.     extern void sig_return();
  323.  
  324.     if (curproc->sighandle[sig] == SIG_IGN)
  325.         return;
  326.     if (curproc->sighandle[sig] == SIG_DFL) {
  327. _default:
  328.         switch(sig) {
  329. #if 0
  330. /* Note: SIGNULL is filtered out in dossig.c and is never actually
  331.  * delivered (its only purpose for the user is to test for the existence of
  332.  * a process, it isn't a real signal). The kernel uses SIGNULL
  333.  * internally, but all such code does the signal handling "by hand"
  334.  * and so no default handling is necessary.
  335.  */
  336.         case SIGNULL:
  337. #endif
  338.         case SIGWINCH:
  339.         case SIGCHLD:
  340. /* SIGFPE is divide by 0; TOS ignores this, so we will too */
  341.         case SIGFPE:
  342.             return;        /* do nothing */
  343.         case SIGSTOP:
  344.         case SIGTSTP:
  345.         case SIGTTIN:
  346.         case SIGTTOU:
  347.             stop(sig);
  348.             return;
  349.         case SIGCONT:
  350.             curproc->sigpending &= ~STOPSIGS;
  351.             return;
  352.  
  353. /* here are the fatal signals. for SIGINT, we use p_term(-32) so that
  354.  * TOS programs that catch ^C via the vector at 0x400 and which expect
  355.  * TOS's error code (-32) to be sent will work. For most other signals,
  356.  * we p_term with an error code; for SIGKILL, we don't want to allow
  357.  * the program any chance to recover, so we call terminate() directly
  358.  * to avoid calling through to the user's terminate vector.
  359.  */
  360.         case SIGINT:        /* ^C */
  361.             if (curproc->domain == DOM_TOS) {
  362.                 p_term(-32);
  363.                 return;
  364.             }
  365.             /* otherwise, fall through */
  366.         default:
  367. #ifdef EXCEPTION_SIGS
  368.             bombs(sig); /* tell the user what happened */
  369. #endif
  370.     /* the "sigmask" check is in case a bus error happens in the user's
  371.      * term_vec code; we don't want to get stuck in an infinite loop!
  372.      */
  373.             if ((curproc->sigmask & 1L) || sig == SIGKILL)
  374.                 terminate(sig << 8, ZOMBIE_Q);
  375.             else
  376.                 p_term(sig << 8);
  377.         }
  378.     }
  379.     else {        /* user wants to handle it himself */
  380.  
  381. /* another kludge: there is one case in which the p_sigreturn mechanism
  382.  * is invoked by the kernel, namely when the user calls Supexec()
  383.  * or when s/he installs a handler for the GEMDOS terminate vector (#0x102)
  384.  * and the program terminates. MiNT fakes the call to user code with
  385.  * signal 0 (SIGNULL); programs that longjmp out of the user function
  386.  * and are later sent back to it again (e.g. if ^C keeps getting pressed
  387.  * and a terminate vector has been installed) will grow the stack without
  388.  * bound unless we watch for this case.
  389.  *
  390.  * Solution (sort of): whenever Pterm() is called, we unwind the
  391.  * stack; otherwise, we let it grow, so that nested Supexec()
  392.  * calls work.
  393.  *
  394.  * Note that SIGNULL is thrown away when sent by user processes, 
  395.  * and the user can't mask it (it's UNMASKABLE), so there is
  396.  * is no possibility of confusion with anything the user does.
  397.  */
  398.         if (sig == 0) {
  399.     /* p_term() sets sigmask to let us know to do Psigreturn */
  400.             if (curproc->sigmask & 1L) {
  401.                 p_sigreturn();
  402.                 curproc->sigmask &= ~1L;
  403.             } else {
  404.                 unwound_stack = 0;
  405.             }
  406.         }
  407.  
  408.         ++curproc->nsigs;
  409.         call = &curproc->ctxt[SYSCALL];
  410. /*
  411.  * what we do is build two fake stack frames; the bottom one is
  412.  * for a call to the user function, with (long)parameter being the
  413.  * signal number; the top one is for sig_return.
  414.  * When the user function returns, it returns to sig_return, which
  415.  * calls into the kernel to restore the context in prev_ctxt
  416.  * (thus putting us back here). We can then continue on our way.
  417.  */
  418.  
  419. /* set a new system stack, with a bit of buffer space */
  420.         oldstack = curproc->sysstack;
  421.         newstack = ((long) ( (&newcurrent) - 2 )) - 12;
  422.  
  423.         if (newstack < (long)curproc->stack + ISTKSIZE + 256) {
  424.             ALERT("stack overflow");
  425.             goto _default;
  426.         }
  427.         else if ((long) curproc->stack + STKSIZE < newstack) {
  428.             FATAL("system stack not in proc structure");
  429.         }
  430.  
  431. /* unwound_stack is set by p_sigreturn() */
  432.         if (sig == 0 && unwound_stack)
  433.             curproc->sysstack = unwound_stack;
  434.         else
  435.             curproc->sysstack = newstack;
  436.         oldsysctxt = *call;
  437.         stack = (long *)(call->sr & 0x2000 ? call->ssp :
  438.                 call->usp);
  439. /*
  440.    Hmmm... here's another potential problem for the signal 0 terminate
  441.    vector: if the program keeps returning back to user mode without
  442.    worrying about the supervisor stack, we'll eventually overflow it.
  443.    However, if the program is in supervisor mode itself, then we don't
  444.    want to stomp on its stack. Temporary solution: ignore the problem,
  445.    the stack's only growing 12 bytes at a time.
  446.  */
  447. /*
  448.  * in addition to the signal number we stuff the vector offset on the
  449.  * stack; if the user is interested they can sniff it, if not ignoring
  450.  * it needs no action on their part. Why do we need this? So that a
  451.  * single SIGFPE handler (for example) can discriminate amongst the
  452.  * multiple things which may get thrown its way
  453.  */
  454.         *(--stack) = (long)call->sfmt & 0xfff;
  455.         *(--stack) = (long)sig;
  456.         *(--stack) = (long)sig_return;
  457.         if (call->sr & 0x2000)
  458.             call->ssp = ((long) stack);
  459.         else
  460.             call->usp = ((long) stack);
  461.         call->pc = (long) curproc->sighandle[sig];
  462.         call->sfmt = call->fstate[0] = 0;    /* don't restart FPU communication */
  463.  
  464.         ((long *)curproc->sysstack)[1] = FRAME_MAGIC;
  465.         ((long *)curproc->sysstack)[2] = oldstack;
  466.         ((long *)curproc->sysstack)[3] = sig;
  467.  
  468.         if (curproc->sigflags[sig] & SA_RESET) {
  469.             curproc->sighandle[sig] = SIG_DFL;
  470.             curproc->sigflags[sig] &= ~SA_RESET;
  471.         }
  472.             
  473.         if (save_context(&newcurrent) == 0 ) {
  474. /*
  475.  * go do the signal; eventually, we'll restore this context (unless the
  476.  * user longjmp'd out of his signal handler). while the user is handling
  477.  * the signal, it's masked out to prevent race conditions. p_sigreturn()
  478.  * will unmask it for us when the user is finished.
  479.  */
  480.             newcurrent.regs[0] = CTXT_MAGIC;
  481.                 /* set D0 so next return is different */
  482.             assert(curproc->magic == CTXT_MAGIC);
  483.             leave_kernel();
  484.             restore_context(call);
  485.         }
  486. /*
  487.  * OK, we get here from p_sigreturn, via the user returning from
  488.  * the handler to sig_return. Restoring the stack and unmasking the
  489.  * signal have been done already for us by p_sigreturn.
  490.  * We should just restore the old system call context
  491.  * and continue with whatever it was we were doing.
  492.  */
  493.         TRACE(("done handling signal"));
  494.         curproc->ctxt[SYSCALL] = oldsysctxt;
  495.         assert(curproc->magic == CTXT_MAGIC);
  496.     }
  497. #undef oldsysctxt
  498. #undef newcurrent
  499. }
  500.  
  501. /*
  502.  * the p_sigreturn system call
  503.  * When called by the user from inside a signal handler, it indicates a
  504.  * desire to restore the old stack frame prior to a longjmp() out of
  505.  * the handler.
  506.  * When called from the sig_return module, it indicates that the user
  507.  * is finished a handler, and we should not only restore the stack
  508.  * frame but also the old context we were working in (which is on the
  509.  * system call stack -- see handle_sig).
  510.  * The syscall pc is "pc_valid_return" in the second case.
  511.  */
  512.  
  513. extern void *pc_valid_return;
  514.  
  515. long ARGS_ON_STACK
  516. p_sigreturn()
  517. {
  518.     CONTEXT *oldctxt;
  519.     long *frame;
  520.     long sig;
  521.  
  522.     unwound_stack = 0;
  523. top:
  524.     frame = (long *)curproc->sysstack;
  525.     frame++;    /* frame should point at FRAME_MAGIC, now */
  526.     sig = frame[2];
  527.     if (*frame != FRAME_MAGIC || (sig < 0) || (sig >= NSIG)) {
  528.         FATAL("Psigreturn: system stack corrupted");
  529.     }
  530.     if (frame[1] == 0) {
  531.         DEBUG(("Psigreturn: frame at %lx points to 0", frame-1));
  532.         return 0;
  533.     }
  534.     unwound_stack = curproc->sysstack;
  535.     TRACE(("Psigreturn(%d)", (int)sig));
  536.  
  537.     curproc->sysstack = frame[1];    /* restore frame */
  538.     curproc->sigmask &= ~(1L<<sig); /* unblock signal */
  539.  
  540.     if (curproc->ctxt[SYSCALL].pc != (long)&pc_valid_return) {
  541. /* here, the user is telling us that a longjmp out of a signal handler is
  542.  * about to occur; so we should unwind *all* the signal frames
  543.  */
  544.         goto top;
  545.     }
  546.     else {
  547.         oldctxt = ((CONTEXT *)(&frame[2])) + 2;
  548.         if (oldctxt->regs[0] != CTXT_MAGIC) {
  549.             FATAL("p_sigreturn: corrupted context");
  550.         }
  551.         assert(curproc->magic == CTXT_MAGIC);
  552.         restore_context(oldctxt);
  553.         return 0;    /* dummy -- this isn't reached */
  554.     }
  555. }
  556.  
  557. /*
  558.  * stop a process because of signal "sig"
  559.  */
  560.  
  561. void
  562. stop(sig)
  563.     int sig;
  564. {
  565.     unsigned int code;
  566.     unsigned long oldmask;
  567.     PROC *p;
  568.  
  569.     code = sig << 8;
  570.  
  571.     if (curproc->pid == 0) {
  572.         FORCE("attempt to stop MiNT");
  573.         return;
  574.     }
  575.  
  576. /* notify parent */
  577.     if (curproc->ptracer) {
  578.         p = curproc->ptracer;
  579.         post_sig(p, SIGCHLD);
  580.     } else {
  581.         p = pid2proc(curproc->ppid);
  582.         if (p && !(p->sigflags[SIGCHLD] & SA_NOCLDSTOP))
  583.             post_sig(p, SIGCHLD);
  584.     }
  585.  
  586.     oldmask = curproc->sigmask;
  587.  
  588.     if (!curproc->ptracer) {
  589.         assert((1L << sig) & STOPSIGS);
  590.         /* mask out most signals */
  591.         curproc->sigmask |= ~(UNMASKABLE | SIGTERM);
  592.     }
  593.  
  594. /* sleep until someone signals us awake */
  595.     sleep(STOP_Q, (long) code | 0177);
  596.  
  597. /* when we wake up, restore the signal mask */
  598.     curproc->sigmask = oldmask;
  599.  
  600. /* and discard any signals that would cause us to stop again */
  601.     curproc->sigpending &= ~STOPSIGS;
  602. }
  603.  
  604. /*
  605.  * interrupt handlers to raise SIGBUS, SIGSEGV, etc. Note that for
  606.  * really fatal errors we reset the handler to SIG_DFL, so that
  607.  * a second such error kills us
  608.  */
  609.  
  610. void
  611. exception(sig)
  612.     int sig;
  613. {
  614.     curproc->sigflags[sig] |= SA_RESET;
  615.     DEBUG(("exception #%d raised", sig));
  616.     raise(sig);
  617. }
  618.  
  619. void
  620. sigbus()
  621. {
  622.     if (curproc->sighandle[SIGBUS] == SIG_DFL)
  623.         report_buserr();
  624.     exception(SIGBUS);
  625. }
  626.  
  627. void
  628. sigaddr()
  629. {
  630.     exception(SIGSEGV);
  631. }
  632.  
  633. void
  634. sigill()
  635. {
  636.     exception(SIGILL);
  637. }
  638.  
  639. void
  640. sigpriv()
  641. {
  642.     raise(SIGPRIV);
  643. }
  644.  
  645. void
  646. sigfpe()
  647. {
  648.     extern short fpu;    /* in main.c */
  649.     
  650.     if (fpu) {
  651.         CONTEXT *ctxt;
  652.  
  653.         ctxt = &curproc->ctxt[SYSCALL];
  654.  
  655.     /* 0x1f38 is a Motorola magic cookie to detect a 68882 idle state frame */
  656.         if (*(ushort *)ctxt->fstate == 0x1f38 && 
  657.             (ctxt->sfmt & 0xfff) >= 0xc0L && (ctxt->sfmt & 0xfff) <= 0xd8L) {
  658.             /* fix a bug in the 68882 - Motorola call it a feature :-) */
  659.             ctxt->fstate[ctxt->fstate[1]] |= 1 << 3;
  660.         }
  661.     }
  662.     raise(SIGFPE);
  663. }
  664.  
  665. void
  666. sigtrap()
  667. {
  668.     raise(SIGTRAP);
  669. }
  670.  
  671. void
  672. haltformat()
  673. {
  674.     FATAL("halt: invalid stack frame format");
  675. }
  676.  
  677. void
  678. haltcpv()
  679. {
  680.     FATAL("halt: coprocessor protocol violation");
  681. }
  682.